﻿//////////////////////////////////////////////////////////////////////////////////
//
// Project            : XNAsteroids
// Module:            : XNAsteroids.GameObjects
// Description        : The Starship.
// 
// Repository         : $URL$
// Created at         : 2010-05-19 00:41
// Last changed by    : $LastChangedBy$
// Revision           : $LastChangedRevision$
// Last Changed       : $LastChangedDate$
// Author             : $Author$
//
// Id:                : $Id$
//
// Copyright:         (c) 2010 Torsten Bär
//
// Published under the MIT License. See license.txt or http://www.opensource.org/licenses/mit-license.php.
//
//////////////////////////////////////////////////////////////////////////////////

using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace XNAsteroids.GameObjects.SpaceObjects
{
   /// <summary>
   /// A StarShip.
   /// </summary>
   public class StarShip : TexturedSpaceObject
   {
      #region Fields

      private VertexPositionTexture[] model;

      #endregion

      #region Properties

      /// <summary>
      /// Gets or sets the heading.
      /// </summary>
      public Vector3 Heading { get; set; }

      /// <summary>
      /// Gets the scale.
      /// </summary>
      private static float Scale { get { return 10; } }

      /// <summary>
      /// Gets the model.
      /// </summary>
      private VertexPositionTexture[] Model { get { return model; } }

      #endregion

      /// <summary>
      /// Initializes a new instance of the <see cref="StarShip"/> class.
      /// </summary>
      /// <param name="game">The game.</param>
      /// <param name="position">The position.</param>
      /// <param name="effect">The effect.</param>
      public StarShip(Game game, Vector3 position, BasicEffect effect)
         : base(game, position, effect)
      {
         Heading = Vector3.Zero;
      }

      #region Methods

      #region overrides

      /// <summary>
      /// Initializes the component. Override this method to load any non-graphics resources and query for any required services.
      /// </summary>
      public override void Initialize()
      {
         CreateModel();
         base.Initialize();
      }

      /// <summary>
      /// Called when graphics resources need to be loaded. Override this method to load any component-specific graphics resources.
      /// </summary>
      protected override void LoadContent()
      {
         Texture = Game.Content.Load<Texture2D>("metal");

         Effect.TextureEnabled = true;
         Effect.VertexColorEnabled = false;
         Effect.Texture = Texture;
      }

      /// <summary>
      /// Called when the DrawableGameComponent needs to be drawn. Override this method with component-specific drawing code. Reference page contains links to related conceptual articles.
      /// </summary>
      /// <param name="gameTime">Time passed since the last call to Draw.</param>
      public override void Draw(GameTime gameTime)
      {
         Matrix transForm = Matrix.CreateScale(Scale) *
                            Matrix.CreateRotationZ((Heading.Y > 0.0f ? 1.0f : -1.0f) *
                                                   (float)Math.Acos(Vector3.Dot(Vector3.UnitX, Heading))) *
                            Matrix.CreateTranslation(Position);

         Effect.World = transForm;

         base.Draw(gameTime);
      }

      /// <summary>
      /// Renders this instance.
      /// </summary>
      protected override void Render()
      {
         GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleFan, Model, 0, 1);
      }

      /// <summary>
      /// Initializes the bounding sphere.
      /// </summary>
      /// <returns></returns>
      protected override BoundingSphere CreateBoundingSphere()
      {
         BoundingSphere sphere = BoundingSphere.CreateFromPoints(Model.Select(vertex => vertex.Position * Scale));
         sphere.Center = Position;
         return sphere;
      }

      #endregion

      #region Helper

      /// <summary>
      /// Creates the model.
      /// </summary>
      private void CreateModel()
      {
         model = new[]
                 {
                    new VertexPositionTexture(new Vector3(1, 0, 0), new Vector2(0, 0)),
                    new VertexPositionTexture(new Vector3(-1, 0.8f, 0), new Vector2(0, 1)),
                    new VertexPositionTexture(new Vector3(-1, -0.8f, 0), new Vector2(1, 1)),
                 };
      }

      #endregion

      #endregion
   }
}
